package com.pactera.madp.cp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pactera.madp.admin.api.entity.SysDept;
import com.pactera.madp.admin.api.entity.SysUser;
import com.pactera.madp.admin.api.feign.RemoteDeptAdminService;
import com.pactera.madp.admin.api.feign.RemoteUserService;
import com.pactera.madp.common.core.exception.CheckedException;
import com.pactera.madp.common.data.tenant.TenantContextHolder;
import com.pactera.madp.common.security.util.SecurityUtils;
import com.pactera.madp.common.sequence.sequence.Sequence;
import com.pactera.madp.cp.api.dto.moments.MomentsPageDTO;
import com.pactera.madp.cp.api.dto.moments.MomentsTaskAddDTO;
import com.pactera.madp.cp.api.dto.moments.MomentsTaskUpdateDTO;
import com.pactera.madp.cp.api.entity.*;
import com.pactera.madp.cp.api.vo.moments.*;
import com.pactera.madp.cp.common.config.FileUploadConfig;
import com.pactera.madp.cp.common.constant.BehaviorTrackFormatConst;
import com.pactera.madp.cp.common.util.WxApiUtils;
import com.pactera.madp.cp.handler.CorpContextHolder;
import com.pactera.madp.cp.mapper.CpMomentsTaskMapper;
import com.pactera.madp.cp.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 朋友圈任务表(CpMomentsTask)表服务实现类
 *
 * @author jun.lei
 * @since 2022-05-13 10:15:47
 */
@AllArgsConstructor
@Slf4j
@Service("cpMomentsTaskService")
public class CpMomentsTaskServiceImpl extends ServiceImpl<CpMomentsTaskMapper, CpMomentsTaskEntity> implements CpMomentsTaskService {

    /**
     * 员工信息
     */
    private IWorkEmployeeService workEmployeeService;
    /**
     * 朋友圈任务-员工信息
     */
    private CpMomentsTaskEmpService momentsTaskEmpService;
    @Autowired
    private FileUploadConfig fileUploadConfig;
    @Autowired
    private CpApprovalService cpApprovalService;
    @Autowired
    private Sequence sequence;
    /**
     * 日期时间格式化常量
     */
    private final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
    /**
     * 远程调用用户信息
     */
    private RemoteUserService remoteUserService;
    /**
     * 朋友圈任务-员工信息
     */
    private CpMomentsTaskEmpService cpMomentsTaskEmpService;
    /**
     * 远程调用部门信息
     */
    private RemoteDeptAdminService remoteDeptService;
    /**
     * 企业信息
     */
    @Resource
    private ICorpService corpService;

    /**
     * 新增朋友圈任务
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional
    public boolean saveMomentsTask(MomentsTaskAddDTO dto) {

        CpMomentsTaskEntity entity = new CpMomentsTaskEntity();

        BeanUtil.copyProperties(dto, entity, "imgUrl", "videoUrl", "linkUrl", "deptId", "employeeId", "beginTime", "endTime");
        entity.setCorpId(CorpContextHolder.getCorpId());
        entity.setTenantId(TenantContextHolder.getTenantId());

        if (dto.getDeptId() != null && !dto.getDeptId().isEmpty()) {
            entity.setDeptId(JSONUtil.toJsonStr(JSONUtil.parse(dto.getDeptId())));
        }
        if (dto.getEmployeeId() != null && !dto.getEmployeeId().isEmpty()) {
            entity.setEmployeeId(JSONUtil.toJsonStr(JSONUtil.parse(dto.getEmployeeId())));
            List<SysUser> sysUsers = remoteUserService.userByIds(dto.getEmployeeId());
            List<String> collect = sysUsers.stream().map(SysUser::getUsername).collect(Collectors.toList());
            entity.setEmployeeWxId(JSONUtil.toJsonStr(JSONUtil.parse(collect)));
        }

        if (dto.getImgUrl() != null && !dto.getImgUrl().isEmpty()) {
            entity.setImgUrl(JSONUtil.toJsonStr(JSONUtil.parse(dto.getImgUrl())));
        }
        if (StrUtil.isNotBlank(dto.getLinkUrl())) {
            entity.setLinkUrl(JSONUtil.toJsonStr(dto.getLinkUrl()));
        }
        if (dto.getVideoUrl() != null && !dto.getVideoUrl().isEmpty()) {
            entity.setVideoUrl(JSONUtil.toJsonStr(JSONUtil.parse(dto.getVideoUrl())));
        }

        Integer createUser = SecurityUtils.getUser().getId();
        entity.setCreateUser(createUser);

        SysUser sysUser = remoteUserService.userById(createUser);
        entity.setCreateUserName(sysUser.getName());

        entity.setBeginTime(DateUtil.toLocalDateTime(DateUtil.parse(dto.getBeginTime() + " 00:00:00")));
        entity.setEndTime(DateUtil.toLocalDateTime(DateUtil.parse(dto.getEndTime() + " 23:59:59")));

        return save(entity);
    }


    /**
     * 修改朋友圈任务
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional
    public boolean updateMomentsTask(MomentsTaskUpdateDTO dto) {
        CpMomentsTaskEntity entity = getOne(Wrappers.<CpMomentsTaskEntity>lambdaQuery().eq(CpMomentsTaskEntity::getStatus, 0).eq(CpMomentsTaskEntity::getId, dto.getId()));
        if (ObjectUtil.isEmpty(entity)) {
            throw new CheckedException("该任务不是待发布任务");
        }
        BeanUtil.copyProperties(dto, entity, "imgUrl", "videoUrl", "linkUrl", "deptId", "employeeId", "beginTime", "endTime");
        entity.setCorpId(CorpContextHolder.getCorpId());
        entity.setTenantId(TenantContextHolder.getTenantId());

        List<String> collect = new LinkedList<>();
        if (dto.getEmployeeId() != null && !dto.getEmployeeId().isEmpty()) {
            collect = remoteUserService.userByIds(dto.getEmployeeId()).stream().map(SysUser::getUsername).collect(Collectors.toList());
        }

        entity.setCreateUser(SecurityUtils.getUser().getId());

        SysUser sysUser = remoteUserService.userByUserName(SecurityUtils.getUser().getUsername());
        entity.setCreateUserName(sysUser.getName());
        entity.setBeginTime(DateUtil.toLocalDateTime(DateUtil.parse(dto.getBeginTime() + " 00:00:00")));
        entity.setEndTime(DateUtil.toLocalDateTime(DateUtil.parse(dto.getEndTime() + " 23:59:59")));

        return update(entity, Wrappers.<CpMomentsTaskEntity>lambdaUpdate().eq(CpMomentsTaskEntity::getId, dto.getId())
                .set(dto.getDeptId() != null && !dto.getDeptId().isEmpty(), CpMomentsTaskEntity::getDeptId, JSONUtil.toJsonStr(JSONUtil.parse(dto.getDeptId())))
                .set(ObjectUtil.isEmpty(dto.getDeptId()) || dto.getDeptId().isEmpty(), CpMomentsTaskEntity::getDeptId, null)
                .set(ObjectUtil.isEmpty(dto.getEmployeeId()) || dto.getEmployeeId().isEmpty(), CpMomentsTaskEntity::getEmployeeWxId, null)
                .set(dto.getEmployeeId() != null && !dto.getEmployeeId().isEmpty(), CpMomentsTaskEntity::getEmployeeWxId, JSONUtil.toJsonStr(JSONUtil.parse(collect)))
                .set(ObjectUtil.isEmpty(dto.getEmployeeId()) || dto.getEmployeeId().isEmpty(), CpMomentsTaskEntity::getEmployeeId, null)
                .set(dto.getEmployeeId() != null && !dto.getEmployeeId().isEmpty(), CpMomentsTaskEntity::getEmployeeId, JSONUtil.toJsonStr(JSONUtil.parse(dto.getEmployeeId())))
                .set(ObjectUtil.isEmpty(dto.getImgUrl()) || dto.getImgUrl().isEmpty(), CpMomentsTaskEntity::getImgUrl, null)
                .set(dto.getImgUrl() != null && !dto.getImgUrl().isEmpty(), CpMomentsTaskEntity::getImgUrl, JSONUtil.toJsonStr(JSONUtil.parse(dto.getImgUrl())))
                .set(MapUtil.isEmpty(dto.getLinkUrl()), CpMomentsTaskEntity::getLinkUrl, null)
                .set(MapUtil.isNotEmpty(dto.getLinkUrl()), CpMomentsTaskEntity::getLinkUrl, JSONUtil.toJsonStr(dto.getLinkUrl()))
                .set(ObjectUtil.isEmpty(dto.getVideoUrl()) || dto.getVideoUrl().isEmpty(), CpMomentsTaskEntity::getVideoUrl, null)
                .set(dto.getVideoUrl() != null && !dto.getVideoUrl().isEmpty(), CpMomentsTaskEntity::getVideoUrl, JSONUtil.toJsonStr(JSONUtil.parse(dto.getVideoUrl()))));
    }

    /**
     * 朋友圈任务分页
     *
     * @param dto
     * @param page
     * @return
     */
    @Override
    public Page<MomentsPageVO> getMomentPage(MomentsPageDTO dto, Page page) {
        List<Integer> stateList = new ArrayList<>();
        if (dto.getState() != null && dto.getState() == 1) {
            // 已发布
            stateList.add(1);
            // 进行中
            stateList.add(2);
        } else {
            // 未发布
            stateList.add(0);
            // 已结束
            stateList.add(3);
            // 待审批
            stateList.add(4);
            // 已驳回
            stateList.add(5);
        }
        page = (Page) page(page, Wrappers.<CpMomentsTaskEntity>lambdaQuery()
                .like(StrUtil.isNotBlank(dto.getCreateUserName()), CpMomentsTaskEntity::getCreateUserName, dto.getCreateUserName())
                .like(StrUtil.isNotBlank(dto.getTitle()), CpMomentsTaskEntity::getTitle, dto.getTitle())
                .in(CpMomentsTaskEntity::getStatus, stateList)
                .ge(ObjectUtil.isNotNull(dto.getStartTime()), CpMomentsTaskEntity::getCreateTime, dto.getStartTime() + " 00:00:00")
                .le(ObjectUtil.isNotNull(dto.getEndTime()), CpMomentsTaskEntity::getCreateTime, dto.getEndTime() + " 23:59:59")
                .orderByDesc(CpMomentsTaskEntity::getCreateTime));
        List<MomentsPageVO> vos = new LinkedList<>();
        List<CpMomentsTaskEntity> list = page.getRecords();
        list.forEach(l -> {
            MomentsPageVO vo = new MomentsPageVO();
            BeanUtil.copyProperties(l, vo, "create_time");
            vo.setCreateTime(DateUtil.format(l.getCreateTime(), "yyyy-MM-dd"));
            List<Integer> employeeIds = JSONUtil.toList(JSONUtil.parseArray(l.getEmployeeId()), Integer.class);
            List<String> visibleRange = new LinkedList<>();
            if (!employeeIds.isEmpty()) {
                List<SysUser> sysUsers = remoteUserService.userByIds(employeeIds);
                List<String> collect = sysUsers.stream().map(SysUser::getName).collect(Collectors.toList());
                visibleRange.addAll(collect);
            }
            List<Integer> deptIds = JSONUtil.toList(JSONUtil.parseArray(l.getDeptId()), Integer.class);
            if (!deptIds.isEmpty()) {
                List<SysDept> deptEntityList = remoteDeptService.getDeptListById(deptIds);
                List<String> collect = deptEntityList.stream().map(SysDept::getName).collect(Collectors.toList());
                visibleRange.addAll(collect);
            }
            vo.setVisibleRange(visibleRange);
            vos.add(vo);
        });
        page.setRecords(vos);
        return page;
    }

    /**
     * 朋友圈任务审核分页
     *
     * @param dto
     * @param page
     * @return
     */
    @Override
    public Page<MomentsPageVO> getMomentApprovalPage(MomentsPageDTO dto, Page page) {
        List<Integer> stateList = new ArrayList<>();
        if (dto.getState() != null && dto.getState() == 1) {
            // 已发布
            stateList.add(1);
            // 进行中
            stateList.add(2);
        } else {
            // 待审批
            stateList.add(4);
            // 已驳回
            stateList.add(5);
        }
        page = (Page) page(page, Wrappers.<CpMomentsTaskEntity>lambdaQuery()
                .like(StrUtil.isNotBlank(dto.getCreateUserName()), CpMomentsTaskEntity::getCreateUserName, dto.getCreateUserName())
                .like(StrUtil.isNotBlank(dto.getTitle()), CpMomentsTaskEntity::getTitle, dto.getTitle())
                .in(CpMomentsTaskEntity::getStatus, stateList)
                .ge(ObjectUtil.isNotNull(dto.getStartTime()), CpMomentsTaskEntity::getCreateTime, dto.getStartTime() + " 00:00:00")
                .le(ObjectUtil.isNotNull(dto.getEndTime()), CpMomentsTaskEntity::getCreateTime, dto.getEndTime() + " 23:59:59")
                .orderByDesc(CpMomentsTaskEntity::getCreateTime));
        List<MomentsPageVO> vos = new LinkedList<>();
        List<CpMomentsTaskEntity> list = page.getRecords();
        list.forEach(l -> {
            MomentsPageVO vo = new MomentsPageVO();
            BeanUtil.copyProperties(l, vo, "create_time");
            vo.setCreateTime(DateUtil.format(l.getCreateTime(), "yyyy-MM-dd"));
            List<Integer> employeeIds = JSONUtil.toList(JSONUtil.parseArray(l.getEmployeeId()), Integer.class);
            List<String> visibleRange = new LinkedList<>();
            if (!employeeIds.isEmpty()) {
                List<SysUser> sysUsers = remoteUserService.userByIds(employeeIds);
                List<String> collect = sysUsers.stream().map(SysUser::getName).collect(Collectors.toList());
                visibleRange.addAll(collect);
            }
            List<Integer> deptIds = JSONUtil.toList(JSONUtil.parseArray(l.getDeptId()), Integer.class);
            if (!deptIds.isEmpty()) {
                List<SysDept> deptEntityList = remoteDeptService.getDeptListById(deptIds);
                List<String> collect = deptEntityList.stream().map(SysDept::getName).collect(Collectors.toList());
                visibleRange.addAll(collect);
            }
            vo.setVisibleRange(visibleRange);
            vos.add(vo);
        });
        page.setRecords(vos);
        return page;
    }

    /**
     * 发布朋友圈任务
     *
     * @param id
     * @return
     */
    @Override
    @Transactional
    public boolean releaseMomentsTask(Integer id) {
        List<Integer> statusList = new ArrayList<>();
        statusList.add(0);
        statusList.add(5);
        CpMomentsTaskEntity entity = getOne(Wrappers.<CpMomentsTaskEntity>lambdaQuery().eq(CpMomentsTaskEntity::getId, id)
                .in(CpMomentsTaskEntity::getStatus, statusList)
                .ge(CpMomentsTaskEntity::getEndTime, LocalDateTime.now()));
        if (ObjectUtil.isEmpty(entity)) {
            throw new CheckedException("该任务可能已发布或者超过任务结束时间");
        }
        entity.setStatus(4);
        return updateById(entity);
    }

    /**
     * 审批朋友圈任务
     *
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean approval(Integer id, String  opinion, Integer state) {
        CpMomentsTaskEntity entity = getOne(Wrappers.<CpMomentsTaskEntity>lambdaQuery().eq(CpMomentsTaskEntity::getId, id)
                .eq(CpMomentsTaskEntity::getStatus, 4)
                .ge(CpMomentsTaskEntity::getEndTime,LocalDateTime.now()));
        if (entity == null && entity.getStatus() != null && !entity.getStatus().equals(4))
            throw new CheckedException("操作失败,您要审核的朋友圈任务当前状态已非4-待审核,原因可能为发布/上架操作已被撤销");

        Integer createUserId = SecurityUtils.getUser().getId();
        String createUserName = SecurityUtils.getUser().getUsername();
        Long approvalId = sequence.nextValue();
        CpApprovalEntity approvalEntity = new CpApprovalEntity();
        approvalEntity.setId(approvalId);
        approvalEntity.setItemId(String.valueOf(entity.getId()));
        approvalEntity.setItemType(6);
        approvalEntity.setApprovalType(state);
        approvalEntity.setApprovalUserId(createUserId);
        approvalEntity.setApprovalUserName(createUserName);
        approvalEntity.setApprovalPreState(entity.getStatus());
        entity.setOpinion(opinion);
        if (state == 1) {
            entity.setStatus(5);
            updateById(entity);
            approvalEntity.setApprovalPostState(5);
            cpApprovalService.save(approvalEntity);
            return true;
        } else {
            approvalEntity.setApprovalPostState(1);
            cpApprovalService.save(approvalEntity);
        }

        saveMediaId(entity);
        entity.setStatus(1);


        List<Integer> employeeIds = JSONUtil.toList(JSONUtil.parseArray(entity.getEmployeeId()), Integer.class);
        List<Integer> deptIds = JSONUtil.toList(JSONUtil.parseArray(entity.getDeptId()), Integer.class);

        List<WorkEmployeeEntity> deptEntityList = new LinkedList<>();
        List<WorkEmployeeEntity> employeeEntityList = new LinkedList<>();

        if (!deptIds.isEmpty()) {
            List<SysDept> lowerDeptsByList = remoteDeptService.getLowerDeptsByList(deptIds);

            deptEntityList = workEmployeeService.list(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                    .in(WorkEmployeeEntity::getWxMainDepartmentId, lowerDeptsByList.stream().map(SysDept::getDeptId).collect(Collectors.toList())));
        }

        if (!employeeIds.isEmpty()) {
            List<SysUser> sysUsers = remoteUserService.userByIds(employeeIds);
            employeeEntityList = workEmployeeService.list(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                    .in(WorkEmployeeEntity::getWxUserId, sysUsers.stream().map(SysUser::getUsername).collect(Collectors.toList())));
        }

        List<WorkEmployeeEntity> collect = Stream.of(employeeEntityList, deptEntityList).flatMap(Collection::stream).collect(Collectors.toList());

        List<CpMomentsTaskEmpEntity> entities = new LinkedList<>();
        List<WorkEmployeeEntity> entityList = collect.stream().distinct().collect(Collectors.toList());

        List<String> list = entityList.stream().map(WorkEmployeeEntity::getWxUserId).collect(Collectors.toList());
        List<SysUser> sysUsers = remoteUserService.userByUserNames(list);

        //朋友圈客户经理信息输入
        sysUsers.forEach(l -> {
            CpMomentsTaskEmpEntity empEntity = new CpMomentsTaskEmpEntity();

            empEntity.setMomentsId(id);
            empEntity.setCommentCount(0);
            empEntity.setStatus(0);
            empEntity.setEmployeeId(l.getUserId());
            empEntity.setEmployeeName(l.getName());
            empEntity.setLikeCount(0);

            entities.add(empEntity);
        });
        momentsTaskEmpService.saveBatch(entities);


        entity.setStartTime(LocalDateTime.now());

        if (entity.getBeginTime().isBefore(LocalDateTime.now())) {
            sendEmployee(entity);

        }

        return updateById(entity);
    }

    private void sendMessage(CpMomentsTaskEntity entity) {

        List<Integer> joinUsers = JSONUtil.toList(JSONUtil.parseArray(entity.getEmployeeId()), Integer.class);
        List<Integer> deptIds = JSONUtil.toList(JSONUtil.parseArray(entity.getDeptId()), Integer.class);
        List<WorkEmployeeEntity> employeeEntityList = new LinkedList<>();
        List<WorkEmployeeEntity> employeeEntities = new LinkedList<>();
        if (!deptIds.isEmpty()) {
            List<SysDept> lowerDeptsByList = remoteDeptService.getLowerDeptsByList(deptIds);

            employeeEntityList = workEmployeeService.list(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                    .in(WorkEmployeeEntity::getWxMainDepartmentId, lowerDeptsByList.stream().map(SysDept::getDeptId).collect(Collectors.toList())));
        }
        if (!joinUsers.isEmpty()) {
            List<String> collect = remoteUserService.userByIds(joinUsers).stream().map(SysUser::getUsername).collect(Collectors.toList());
            employeeEntities = workEmployeeService
                    .list(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                            .in(WorkEmployeeEntity::getWxUserId, collect));
        }

        employeeEntities.addAll(employeeEntityList);
        List<WorkEmployeeEntity> collect = Stream.of(employeeEntities, employeeEntityList)
                .flatMap(Collection::stream).distinct().collect(Collectors.toList());

        //发送金融提醒给客户经理
        collect.forEach(ll -> {
            Integer corpId = ll.getCorpId();
            String wxCorpId = corpService.getById(corpId).getWxCorpId();
            com.alibaba.fastjson.JSONObject object = new com.alibaba.fastjson.JSONObject();

            object.put("content", StrUtil.format(BehaviorTrackFormatConst.MOMENTSTASKTOEOMPLOYEE, ll.getName(), ll.getWxUserId()));

            com.alibaba.fastjson.JSONObject jsonObject = new com.alibaba.fastjson.JSONObject();
            jsonObject.put("touser", ll.getWxUserId());
            jsonObject.put("msgtype", "text");
            jsonObject.put("agentid", corpService.getWxSendMsgAgentIdByWxCorpId(wxCorpId));
            jsonObject.put("text", object);
            String s = jsonObject.toString();
            WxApiUtils.sendMsgToEmployeeByString(s, corpId, wxCorpId);
        });
    }

    /**
     * 获取朋友圈发布任务详情
     *
     * @param id
     * @return
     */
    @Override
    public MomentsDetailsVO getMomentsDetails(Integer id) {

        MomentsDetailsVO vo = new MomentsDetailsVO();
        CpMomentsTaskEntity entity = getById(id);
        BeanUtil.copyProperties(entity, vo, "linkUrl", "videoUrl", "imgUrl");

        List<Integer> deptIds = JSONUtil.toList(JSONUtil.parseArray(entity.getDeptId()), Integer.class);
        if (!deptIds.isEmpty()) {
            List<SysDept> listById = remoteDeptService.getDeptListById(deptIds);
            List<MomentsDetailsVO.DeptS> deptS = new LinkedList<>();
            listById.forEach(l -> {
                MomentsDetailsVO.DeptS s = new MomentsDetailsVO.DeptS();
                s.setDeptIdName(l.getName());
                s.setDeptIds(l.getDeptId());
                deptS.add(s);
            });
            vo.setDeptS(deptS);

        }

        List<String> videoUrl = JSONUtil.toList(JSONUtil.parseArray(entity.getVideoUrl()), String.class);
        vo.setVideoUrl(videoUrl);
        List<String> imgUrl = JSONUtil.toList(JSONUtil.parseArray(entity.getImgUrl()), String.class);
        vo.setImgUrl(imgUrl);
        List<Integer> employeeIds = JSONUtil.toList(JSONUtil.parseArray(entity.getEmployeeId()), Integer.class);

        if (!employeeIds.isEmpty()) {

            List<SysUser> sysUsers = remoteUserService.userByIds(employeeIds);
            LinkedList<MomentsDetailsVO.EmployeeList> employeeLists = new LinkedList<>();

            sysUsers.forEach(l -> {
                MomentsDetailsVO.EmployeeList list = new MomentsDetailsVO.EmployeeList();
                list.setEmployeeId(l.getUserId());
                list.setEmployeeName(l.getName());
                employeeLists.add(list);
            });

            vo.setEmployeeLists(employeeLists);

        }

        vo.setBeginTime(DateUtil.formatDate(DateUtil.date(entity.getBeginTime())));
        vo.setEndTime(DateUtil.formatDate(DateUtil.date(entity.getEndTime())));


        JSONObject linkUrl = JSONUtil.parseObj(entity.getLinkUrl());
        if (MapUtil.isNotEmpty(linkUrl)) {
            vo.setLinkUrl(linkUrl);
        }

        return vo;
    }

    /**
     * 朋友圈任务撤销
     *
     * @param id
     * @return
     */
    @Override
    public Boolean revoke(Integer id) {
        CpMomentsTaskEntity entity = getById(id);
        entity.setStatus(0);
        this.baseMapper.updateById(entity);
        return Boolean.TRUE;
    }

    /**
     * 修改朋友圈任务状态值
     */
    @Override
    @Async
    @Transactional
    public void updateStatus() {
        List<CpMomentsTaskEntity> list = list(Wrappers.<CpMomentsTaskEntity>lambdaQuery()
                .eq(CpMomentsTaskEntity::getStatus, 1)
                .le(CpMomentsTaskEntity::getBeginTime, LocalDateTime.now()));

        list.forEach(entity -> {
            if (entity.getFilterType().equals(0)) {
                String s = releaseMomentsTaskPrivate(entity);
                if (StrUtil.isNotBlank(s)) {
                    String result = WxApiUtils.getMomentTaskResult(entity.getCorpId(), s);
                    JSONObject jsonObject = JSONUtil.parseObj(result);
                    String momentId = JSONUtil.toJsonStr(jsonObject.getStr("moment_id"));
                    if (StrUtil.isNotBlank(momentId)) {
                        entity.setMomentId(momentId);
                    } else {
                        String momentId1 = getMomentId(entity.getCorpId(), s, 0);
                        entity.setMomentId(momentId1);
                    }
                }
            }else {
                sendMessage(entity);
            }
            entity.setStatus(2);
        });

        if (!list.isEmpty()) {
            updateBatchById(list);
        }

        List<CpMomentsTaskEntity> endList = list(Wrappers.<CpMomentsTaskEntity>lambdaQuery()
                .eq(CpMomentsTaskEntity::getStatus, 2)
                .le(CpMomentsTaskEntity::getEndTime, LocalDateTime.now()));
        endList.forEach(l -> {
            l.setStatus(3);
        });
        if (!endList.isEmpty()) {
            updateBatchById(endList);
        }
    }

    /**
     * 发送消息提醒成员
     *
     * @param entity
     */
    public void sendEmployee(CpMomentsTaskEntity entity) {
        if (entity.getFilterType().equals(0)) {
            String s = releaseMomentsTaskPrivate(entity);
            if (StrUtil.isNotBlank(s)) {
                String result = WxApiUtils.getMomentTaskResult(entity.getCorpId(), s);
                JSONObject jsonObject = JSONUtil.parseObj(result);
                String momentId = JSONUtil.toJsonStr(jsonObject.getStr("moment_id"));
                if (StrUtil.isNotBlank(momentId)) {
                    entity.setMomentId(momentId);
                } else {
                    entity.setMomentId(getMomentId(entity.getCorpId(), s, 0));
                }
            }
        }else {
            sendMessage(entity);
        }
        entity.setStatus(2);
        updateById(entity);
    }

    /**
     * 上传素材
     *
     * @param entity
     */
    private void saveMediaId(CpMomentsTaskEntity entity) {
        List<String> mediaId = new LinkedList<>();

        List<String> imgUrls = JSONUtil.toList(JSONUtil.parseArray(entity.getImgUrl()), String.class);
        if (!imgUrls.isEmpty()) {
            imgUrls.forEach(l -> {
                String[] split = l.split("/");
                String fileUrl = fileUploadConfig.getRealPath() + File.separatorChar + split[split.length - 1];
                File file = new File(fileUrl);
                String s = null;
                try {
                    log.info("文件名为：" + file.getName());
                    s = WxApiUtils.uploadAttachment(entity.getCorpId(), file, "image", 1);
                } catch (NullPointerException e) {
                    log.info("临时素材库已有素材，无法上传");
                }
                if (StrUtil.isNotBlank(s)) {
                    mediaId.add(s);
                }
            });
        }

        List<String> videoUrl = JSONUtil.toList(JSONUtil.parseArray(entity.getVideoUrl()), String.class);
        if (!videoUrl.isEmpty()) {
            videoUrl.forEach(l -> {
                String[] split = l.split("/");
                String fileUrl = fileUploadConfig.getRealPath() + File.separatorChar + split[split.length - 1];
                File file = new File(fileUrl);
                String s = null;
                try {
                    log.info("文件名为：" + file.getName());
                    s = WxApiUtils.uploadAttachment(entity.getCorpId(), file, "video", 1);
                } catch (NullPointerException e) {
                    log.info("临时素材库已有素材，无法上传");
                }
                if (StrUtil.isNotBlank(s)) {
                    mediaId.add(s);
                }
            });
        }

        JSONObject link = JSONUtil.parseObj(entity.getLinkUrl());
        if (MapUtil.isNotEmpty(link)) {
            String imgUrl = link.getStr("img_url");
            String[] split = imgUrl.split("/");
            String fileUrl = fileUploadConfig.getRealPath() + File.separatorChar + split[split.length - 1];
            File file = new File(fileUrl);
            String s = null;
            try {
                log.info("文件名为：" + file.getName());
                s = WxApiUtils.uploadAttachment(entity.getCorpId(), file, "image", 1);
            } catch (NullPointerException e) {
                log.info("临时素材库已有素材，无法上传");
            }
            if (StrUtil.isNotBlank(s)) {
                mediaId.add(s);
            }
        }

        entity.setMediaId(JSONUtil.toJsonStr(mediaId));
    }


    /**
     * 获取momentId
     * @param corpId
     * @param jobId
     * @param count
     * @return 从企业微信返回MomentId 可能为空
     */
    private String getMomentId(Integer corpId, String jobId, Integer count) {
        String momentId = null;
        try {
            String result = WxApiUtils.getMomentTaskResult(corpId, jobId);
            JSONObject jsonObject = JSONUtil.parseObj(result);
            momentId = JSONUtil.toJsonStr(jsonObject.getStr("moment_id"));
            if (StrUtil.isNotBlank(momentId) || count > 5) {
                return momentId;
            }
            count += 1;
            Thread.sleep(2000);
            return  getMomentId(corpId, jobId, count);

        } catch (Exception e) {
            log.info(e.getMessage());
        }
        return momentId;
    }

    /**
     * 获取朋友圈任务详情
     *
     * @param id
     * @return
     */
    @Override
    public MomentsTaskDetailsVO getMomentsDetailsAll(Integer id) {

        CpMomentsTaskEntity entity = getById(id);
        if (ObjectUtil.isNull(entity)) {
            throw new CheckedException("当前任务不存在");
        }

        if (entity.getFilterType().equals(0)) {
            updateMomentsEmp(entity);
        } else {
            sendYourselfTsk(entity);
        }
        List<CpMomentsTaskEmpEntity> empEntities = cpMomentsTaskEmpService.list(Wrappers.<CpMomentsTaskEmpEntity>lambdaQuery()
                .eq(CpMomentsTaskEmpEntity::getMomentsId, entity.getId()));

        int likeCount = empEntities.stream().mapToInt(CpMomentsTaskEmpEntity::getLikeCount).sum();
        int commentCount = empEntities.stream().mapToInt(CpMomentsTaskEmpEntity::getCommentCount).sum();
        int successCount = (int) empEntities.stream().filter(p -> p.getStatus().equals(1)).count();
        int unaccomplishedCount = (int) empEntities.stream().filter(p -> p.getStatus().equals(0)).count();
        int counts = empEntities.size();

        MomentsTaskDetailsVO vo = new MomentsTaskDetailsVO();

        vo.setCounts(counts);
        vo.setId(entity.getId());
        vo.setCommentCounts(commentCount);
        vo.setSuccessCounts(successCount);
        vo.setUnaccomplishedCounts(unaccomplishedCount);
        vo.setLikeCounts(likeCount);


        return vo;
    }

    /**
     * 定时同步朋友圈任务详情
     */
    @Override
    @Transactional
    public void synMomentsTaskDetails() {

        List<CpMomentsTaskEntity> list = list(Wrappers.<CpMomentsTaskEntity>lambdaQuery().eq(CpMomentsTaskEntity::getStatus, 2));
        list.forEach(l -> {
            if (l.getFilterType().equals(0)) {
                updateMomentsEmp(l);
            } else {
                sendYourselfTsk(l);
            }
        });
    }

    /**
     * 朋友圈任务详情分页
     *
     * @param id
     * @return
     */
    @Override
    public Page<MomentsTaskDetailsPageVO> getMomentTaskDetailsPage(Integer id, Page page, String name) {
        CpMomentsTaskEntity entity = getById(id);
        if (ObjectUtil.isNull(entity)) {
            throw new CheckedException("当前任务不存在");
        }

        if (entity.getFilterType().equals(0)) {
            updateMomentsEmp(entity);
        } else {
            sendYourselfTsk(entity);
        }

        page = (Page) cpMomentsTaskEmpService.page(page, Wrappers.<CpMomentsTaskEmpEntity>lambdaQuery()
                .eq(CpMomentsTaskEmpEntity::getMomentsId, id)
                .like(StrUtil.isNotBlank(name), CpMomentsTaskEmpEntity::getEmployeeName, name)
                .orderByDesc(CpMomentsTaskEmpEntity::getCreateTime));
        LinkedList<MomentsTaskDetailsPageVO> vos = new LinkedList<>();

        List<CpMomentsTaskEmpEntity> list = page.getRecords();
        list.forEach(l -> {
            MomentsTaskDetailsPageVO vo = new MomentsTaskDetailsPageVO();
            BeanUtil.copyProperties(l, vo);

            vos.add(vo);
        });

        page.setRecords(vos);
        return page;
    }

    /**
     * 删除到期期30天 任务
     */
    @Override
    @Async
    public void deleteOverdueTasks() {
        List<CpMomentsTaskEntity> overdueTasks = baseMapper.getOverdueTasks();
        if (!overdueTasks.isEmpty()) {
            removeByIds(overdueTasks.stream().map(CpMomentsTaskEntity::getId).collect(Collectors.toList()));
        }
    }

    /**
     * 修改朋友圈任务发布详情-自己发布
     *
     * @param entity
     */
    public void sendYourselfTsk(CpMomentsTaskEntity entity) {
        List<CpMomentsTaskEmpEntity> list = cpMomentsTaskEmpService.list(Wrappers.<CpMomentsTaskEmpEntity>lambdaQuery()
                .eq(CpMomentsTaskEmpEntity::getMomentsId, entity.getId()));

        list.forEach(l -> {
            SysUser sysUser = remoteUserService.userById(l.getEmployeeId());

            Map<String, Object> hashMap = new HashMap<>();
            hashMap.put("start_time", getInstance(entity.getStartTime()) / 1000);
            hashMap.put("end_time", System.currentTimeMillis() / 1000);
            hashMap.put("creator", sysUser.getUsername());
            hashMap.put("filter_type", 1);


            String momentList = WxApiUtils.getMomentList(entity.getCorpId(), JSONUtil.toJsonStr(hashMap));
            JSONObject parseObj = JSONUtil.parseObj(momentList);
            String parseObjStr = parseObj.getStr("moment_list");

            JSONArray jsonArray = JSONUtil.parseArray(parseObjStr);
            JSONArray jsonArrays = new JSONArray();
            String nextCursor = parseObj.getStr("next_cursor");

            if (StrUtil.isNotBlank(nextCursor)) {
                hashMap.put("cursor", nextCursor);
                JSONArray cursorList = getCursorList(entity.getCorpId(), hashMap, nextCursor, jsonArrays);
                jsonArray.addAll(cursorList);
            }

            List<Object> collect = jsonArray.stream().distinct().collect(Collectors.toList());
            collect.forEach(ll -> {
                JSONObject object = JSONUtil.parseObj(ll);
                String momentId = object.getStr("moment_id");
                String text = object.getStr("text");
                JSONObject jsonObject = JSONUtil.parseObj(text);
                String content = jsonObject.getStr("content");

                if (content.contentEquals(entity.getContent())) {
                    l.setStatus(1);

                    HashMap<String, Object> map = new HashMap<>();
                    map.put("moment_id", momentId);
                    map.put("userid", sysUser.getUsername());


                    String comments = WxApiUtils.getMomentComments(entity.getCorpId(), JSONUtil.toJsonStr(map));
                    if (StrUtil.isNotBlank(comments)) {
                        JSONObject jsonObject1 = JSONUtil.parseObj(comments);
                        JSONArray commentList = JSONUtil.parseArray(jsonObject1.getStr("comment_list"));
                        JSONArray likeList = JSONUtil.parseArray(jsonObject1.getStr("like_list"));

                        String cursor = jsonObject1.getStr("next_cursor");
                        if (StrUtil.isNotBlank(cursor)) {
                            getMomentCommentsCursor(entity.getCorpId(), map, cursor, commentList, likeList);
                        }

                        l.setLikeCount(likeList.size());
                        l.setCommentCount(commentList.size());
                    }

                }
            });
        });
        if (!list.isEmpty()) {
            cpMomentsTaskEmpService.updateBatchById(list);
        }
    }


    private void getMomentCommentsCursor(Integer corpId, Map<String, Object> map, String cursor, JSONArray commentList, JSONArray likeList) {
        map.put("cursor", cursor);
        String momentList = WxApiUtils.getMomentList(corpId, JSONUtil.toJsonStr(map));
        JSONObject parseObj = JSONUtil.parseObj(momentList);
        cursor = parseObj.getStr("next_cursor");
        String commentLists = parseObj.getStr("comment_list");
        String likeLists = parseObj.getStr("like_list");
        JSONArray commentListArray = JSONUtil.parseArray(commentLists);
        JSONArray likeListArray = JSONUtil.parseArray(likeLists);
        if (StrUtil.isNotBlank(cursor)) {
            getMomentCommentsCursor(corpId, map, cursor, commentList, likeList);
        }
        commentList.addAll(commentListArray);
        likeList.addAll(likeListArray);
    }


    /**
     * 递归调用获取企业全部的发表列表
     *
     * @param corpId
     * @param hashMap
     * @param nextCursor
     * @param jsonArray
     * @return
     */
    private JSONArray getCursorList(Integer corpId, Map<String, Object> hashMap, String nextCursor, JSONArray jsonArray) {
        hashMap.put("cursor", nextCursor);
        String momentList = WxApiUtils.getMomentList(corpId, JSONUtil.toJsonStr(hashMap));
        JSONObject parseObj = JSONUtil.parseObj(momentList);
        nextCursor = parseObj.getStr("next_cursor");
        String parseObjStr = parseObj.getStr("moment_list");
        JSONArray jsonArrays = JSONUtil.parseArray(parseObjStr);
        jsonArray.addAll(jsonArrays);
        if (StrUtil.isNotBlank(nextCursor)) {
            getCursorList(corpId, hashMap, nextCursor, jsonArray);
        }
        return jsonArray;
    }

    /**
     * 修改朋友圈任务发布详情-企业发布
     *
     * @param entity
     */
    public void updateMomentsEmp(CpMomentsTaskEntity entity) {

        HashMap<String, Object> map = new HashMap<>();
        if (StrUtil.isNotBlank(entity.getMomentId())) {
            map.put("moment_id", entity.getMomentId());
        }

        String task = WxApiUtils.getMomentTask(entity.getCorpId(), JSONUtil.toJsonStr(map));
        List<MomentsTaskVO> strings = JSONUtil.toList(JSONUtil.parseArray(task), MomentsTaskVO.class);
        strings.forEach(l -> {
            SysUser sysUser = remoteUserService.userByUserName(l.getUserid());

            CpMomentsTaskEmpEntity empEntity = cpMomentsTaskEmpService.getOne(Wrappers.<CpMomentsTaskEmpEntity>lambdaQuery()
                    .eq(CpMomentsTaskEmpEntity::getEmployeeId, sysUser.getUserId())
                    .eq(CpMomentsTaskEmpEntity::getMomentsId, entity.getId()));
            if (ObjectUtil.isNotNull(empEntity)) {
                empEntity.setStatus(l.getPublishStatus());
                cpMomentsTaskEmpService.updateById(empEntity);
            }

        });

        List<CpMomentsTaskEmpEntity> list = cpMomentsTaskEmpService.list(Wrappers.<CpMomentsTaskEmpEntity>lambdaQuery()
                .eq(CpMomentsTaskEmpEntity::getMomentsId, entity.getId()));
        list.forEach(l -> {
            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("moment_id", entity.getMomentId());

            SysUser sysUser = remoteUserService.userById(l.getEmployeeId());

            hashMap.put("userid", sysUser.getUsername());


            String comments = WxApiUtils.getMomentComments(entity.getCorpId(), JSONUtil.toJsonStr(hashMap));
            if (StrUtil.isNotBlank(comments)) {
                JSONObject jsonObject = JSONUtil.parseObj(comments);
                JSONArray commentList = JSONUtil.parseArray(jsonObject.getStr("comment_list"));
                JSONArray likeList = JSONUtil.parseArray(jsonObject.getStr("like_list"));

                String cursor = jsonObject.getStr("next_cursor");
                if (StrUtil.isNotBlank(cursor)) {
                    getMomentCommentsCursor(entity.getCorpId(), map, cursor, commentList, likeList);
                }

                l.setLikeCount(likeList.size());
                l.setCommentCount(commentList.size());
            }

        });
        if (!list.isEmpty()) {
            cpMomentsTaskEmpService.updateBatchById(list);
        }

    }


    private long getInstance(LocalDateTime dateTime) {

        DateFormat df = new SimpleDateFormat(DATE_FORMAT);
        Date date = null;
        try {
            date = df.parse(DateUtil.format(dateTime, DATE_FORMAT));
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.getTimeInMillis();
    }


    /**
     * 发送 发布朋友圈到企业微信
     *
     * @param entity
     * @return
     */
    private String releaseMomentsTaskPrivate(CpMomentsTaskEntity entity) {

        Map<String, Object> map = new HashMap<>();

        Map<String, String> textMap = new HashMap<>();
        textMap.put("content", entity.getContent());

        List<Map<String, Object>> attachmentsList = new LinkedList<>();
        Map<String, Object> hashMap = new HashMap<>();


        if (StrUtil.isNotBlank(entity.getImgUrl())) {
            List<String> list = JSONUtil.toList(JSONUtil.parseArray(entity.getMediaId()), String.class);
            list.forEach(l -> {
                Map<String, Object> map1 = new HashMap<>();
                Map<String, String> image = new HashMap<>();
                image.put("media_id", l);
                hashMap.put("msgtype", "image");
                hashMap.put("image", image);
                map1.putAll(hashMap);
                attachmentsList.add(map1);
                hashMap.clear();
            });

        }

        if (StrUtil.isNotBlank(entity.getVideoUrl())) {
            List<String> list = JSONUtil.toList(JSONUtil.parseArray(entity.getMediaId()), String.class);
            list.forEach(l -> {
                Map<String, Object> map1 = new HashMap<>();
                hashMap.put("msgtype", "video");
                Map<String, String> video = new HashMap<>();
                video.put("media_id", l);
                hashMap.put("video", video);
                map1.putAll(hashMap);
                attachmentsList.add(map1);
                hashMap.clear();
            });

        }

        if (StrUtil.isNotBlank(entity.getLinkUrl())) {
            Map<String, Object> map1 = new HashMap<>();
            JSONObject link = JSONUtil.parseObj(entity.getLinkUrl());
            String title = link.getStr("title");
            String url = link.getStr("url");
            List<String> list = JSONUtil.toList(JSONUtil.parseArray(entity.getMediaId()), String.class);
            HashMap<String, String> linkMap = new HashMap<>();
            linkMap.put("title", title);
            linkMap.put("url", url);
            linkMap.put("media_id", list.get(0));
            hashMap.put("msgtype", "link");
            hashMap.put("link", linkMap);
            map1.putAll(hashMap);
            attachmentsList.add(map1);
            hashMap.clear();
        }

        Map<String, Object> visibleRangeMap = new HashMap<>();
        Map<String, Object> senderList = new HashMap<>();
        List<String> employeeWxIds = JSONUtil.toList(JSONUtil.parseArray(entity.getEmployeeWxId()), String.class);

        List<Integer> deptIds = JSONUtil.toList(JSONUtil.parseArray(entity.getDeptId()), Integer.class);

        if (!employeeWxIds.isEmpty()) {
            senderList.put("user_list", employeeWxIds);
        }
        if (!deptIds.isEmpty()) {
            List<SysDept> deptsByList = remoteDeptService.getLowerDeptsByList(deptIds);

            senderList.put("department_list", deptsByList.stream().map(SysDept::getDeptId).collect(Collectors.toList()));
        }

        visibleRangeMap.put("sender_list", senderList);

        map.put("text", textMap);
        map.put("attachments", attachmentsList);
        map.put("visible_range", visibleRangeMap);
        String str = JSONUtil.toJsonStr(map);
        return WxApiUtils.addMomentTask(entity.getCorpId(), str);
    }


}
